package edu.drexel.info636.assignments.models;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import lombok.Getter;
import lombok.Setter;

import org.apache.commons.math3.stat.regression.SimpleRegression;

/**
 * Represents a record in the system.
 * 
 * @author Chase Miller
 *
 */
public class RecordList {

    @Getter
    @Setter
    private String filePath;

    @Getter
    private ArrayList<Record> items;

    private SimpleRegression regression;

    /**
     * Creates a new instance of this class.
     */
    public RecordList() {
	this.items = new ArrayList<Record>();
	this.regression = new SimpleRegression();
    }

    /**
     * Creates a new instance of this class from the specified reader.
     * 
     * @param reader
     */
    public RecordList(BufferedReader reader) {
	this();
	this.createFrom(reader);
    }

    /**
     * Creates a record object from a buffered reader.
     * 
     * @param reader
     *            - The reader.
     * @return - A Record object.
     */
    private void createFrom(BufferedReader reader) {
	try {
	    String line = reader.readLine();

	    while (line != null) {
		Record newItem = new Record(line);

		this.items.add(newItem);

		line = reader.readLine();
	    }
	} catch (IOException e) {
	}
    }

    /**
     * Returns a string representation of this object: one record item per row.
     */
    public String toString() {
	StringBuilder stringToReturn = new StringBuilder();

	synchronized (this.items) {
	    for (Record next : this.items) {
		stringToReturn.append(next + System.lineSeparator());
	    }
	}

	// Now add b0 and b1
	String bZero = this.getBzero();
	String bOne = this.getBOne();
	stringToReturn.append(System.lineSeparator() + "B0 for this dataset is " + bZero + " and B1 is " + bOne);

	return stringToReturn.toString();
    }

    /**
     * Writes this record to the provided PrintWriter.
     * 
     * @param writer
     *            - The PrintWriter to write to.
     */
    public void write(PrintWriter writer) {
	for (Record next : this.items) {
	    writer.println(next.toString());
	}
    }

    /**
     * Returns the B0 (the intercept of the regression line) for this list
     * 
     * @return
     */
    public String getBzero() {
	this.populateRegression();
	double bZero = this.regression.getIntercept();
	return String.valueOf(bZero);
    }

    /**
     * Returns the B1 (the slope of the regression line) for this list.
     * 
     * @return
     */
    public String getBOne() {
	this.populateRegression();
	double bOne = this.regression.getSlope();
	return String.valueOf(bOne);
    }

    /**
     * Calculates the regression for this data set. If we didn't expose this
     * class's "items" field we could have avoided this and added to the
     * SimpleRegression object whenever we added to the ArrayList.
     */
    private void populateRegression() {
	this.regression.clear();

	for (Record record : this.items) {
	    ArrayList<Double> recordSet = record.getNumberSet();

	    if (recordSet.size() >= 2 && recordSet.get(0) != null && recordSet.get(1) != null) {
		this.regression.addData(recordSet.get(0), recordSet.get(1));
	    }
	}
    }
}
